using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.IO;
using Lime49;
using LockCrypt.Core;
using LockCrypt.Mobile.Properties;
using System.Resources;
using System.Collections;
using LockCrypt.DAL;

namespace LockCrypt.Mobile {
    public partial class FrmMain : Form {
        //private ResourceManager res = new ResourceManager("LockCrypt.Mobile.Properties.Resources", typeof(LockCrypt).Assembly);
        //private IGroup currentGroup;
        private string currentGroupId;
        
        public FrmMain() {
            InitializeComponent();
            try {
                itmAbout.Click += (s, e) => { ShowAbout(); };
                itmOptions.Click += (s, e) => { ShowOptions(); };
                //itmSaveChanges.Click += (s, e) => { settings.SaveDatabase(); };
                itmHelp.Click += (s, e) => {
                    System.Diagnostics.Process.Start(Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.GetName().CodeBase), "lockcrypt.htm"), null);
                };
                itmBack.Click += (s, e) => {
                    if(currentGroupId == null) {
                        Application.Exit();
                    } else {
                        ShowGroup(currentGroupId, true);
                    }
                };
                itmAddAccount.Click += new EventHandler(itmAddAccount_Click);
                itmAddGroup.Click += new EventHandler(itmAddGroup_Click);
                itmCtxAddAccount.Click += new EventHandler(itmAddAccount_Click);
                itmCtxAddGroup.Click += new EventHandler(itmCtxAddGroup_Click);
                itmMenu.Popup += new EventHandler(itmMenu_Popup);
                mnuCtxAccountList.Popup += new EventHandler(itmMenu_Popup);
                itmEdit.Click += new EventHandler(itmEdit_Click);
                itmCtxEdit.Click += new EventHandler(itmEdit_Click);
                itmDelete.Click += new EventHandler(itmDelete_Click);
                itmCtxDelete.Click += new EventHandler(itmDelete_Click);
                itmManageTypes.Click += (s, e) => {
                    using(FrmManageTypes frmManageTypes = new FrmManageTypes()) {
                        frmManageTypes.ShowDialog();
                    }
                };
                lstAccounts.Activation = ItemActivation.OneClick;
                lstAccounts.ItemActivate += new EventHandler(lstAccounts_ItemActivate);
                lstAccounts.SmallImageList = WinMobileUtils.TemplateImages;
                lstAccounts.Columns.Add(I18nUtils.GetString("Strings", "Name"), this.Width, HorizontalAlignment.Left);
                ShowGroup(null, false);
            } catch(Exception e) {
                MessageBox.Show(I18nUtils.GetString("Errors", "Error") + " #5: " + e.Message, I18nUtils.GetString("Errors", "Error"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                Application.Exit();
            }
        }

        /// <summary>
        /// Shows a form to add a new account.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void itmAddAccount_Click(object sender, EventArgs e) {
            using(FrmEditAccount frmEditAccount = new FrmEditAccount(currentGroupId)) {
                if(frmEditAccount.ShowDialog() == DialogResult.OK) {
                    try {
                        DalConfigurationManager.Provider.AddAccounts(new[] { frmEditAccount.Account }, null);
                    } catch(Exception ex) {
                        MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "ErrorSaving"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                    }
                    RefreshView();
                }
            }
        }

        /// <summary>
        /// Shows a form to add a new group.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void itmCtxAddGroup_Click(object sender, EventArgs e) {
            string parentId = null;
            if(lstAccounts.SelectedIndices.Count > 0) {
                ListViewItem selectedItem = lstAccounts.Items[lstAccounts.SelectedIndices[0]];
                parentId = (selectedItem.Tag as INestable).ID;
            }
            using(FrmEditGroup frmEditGroup = new FrmEditGroup(parentId)) {
                if(frmEditGroup.ShowDialog() == DialogResult.OK) {
                    try {
                        DalConfigurationManager.Provider.AddGroups(new[] { frmEditGroup.Group }, null);
                    } catch(Exception ex) {
                        MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "ErrorSaving"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                    }
                    RefreshView();
                }
            }
        }

        /// <summary>
        /// Shows a form to add a new group.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void itmAddGroup_Click(object sender, EventArgs e) {
            using(FrmEditGroup frmEditGroup = new FrmEditGroup(currentGroupId)) {
                if(frmEditGroup.ShowDialog() == DialogResult.OK) {
                    try {
                        DalConfigurationManager.Provider.AddGroups(new[] { frmEditGroup.Group }, null);
                    } catch(Exception ex) {
                        MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "ErrorSaving"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                    }
                    RefreshView();
                }
            }
        }

        /// <summary>
        /// Sets the appropriate text depending on whether an account or group is selected and disables the menu items if there are no accounts.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void itmMenu_Popup(object sender, EventArgs e) {
            if(lstAccounts.SelectedIndices.Count > 0) {
                itmEdit.Enabled = true;
                itmDelete.Enabled = true;
                itmCtxEdit.Enabled = true;
                itmCtxDelete.Enabled = true;
                ListViewItem selectedItem = lstAccounts.Items[lstAccounts.SelectedIndices[0]];
                INestable item = selectedItem.Tag as INestable;
                if(item is IAccount) {
                            itmCtxEdit.Text = I18nUtils.GetString("Strings", "EditAccount");
                            itmCtxDelete.Text = I18nUtils.GetString("Strings", "DeleteAccount");
                            itmEdit.Text = I18nUtils.GetString("Strings", "EditAccount");
                            itmDelete.Text = I18nUtils.GetString("Strings", "DeleteAccount");
                } else if(item is IGroup) {
                    itmCtxEdit.Text = I18nUtils.GetString("Strings", "EditGroup");
                    itmCtxDelete.Text = I18nUtils.GetString("Strings", "DeleteGroup");
                    itmEdit.Text = I18nUtils.GetString("Strings", "EditGroup");
                    itmDelete.Text = I18nUtils.GetString("Strings", "DeleteGroup");
                } else {
                    string editText = I18nUtils.GetString("Strings", "Edit"),
                           deleteText = I18nUtils.GetString("Strings", "Delete");
                    itmCtxEdit.Text = editText;
                    itmCtxDelete.Text = deleteText;
                    itmEdit.Text = editText;
                    itmDelete.Text = deleteText;
                    itmEdit.Enabled = false;
                    itmDelete.Enabled = false;
                    itmCtxEdit.Enabled = false;
                    itmCtxDelete.Enabled = false;
                }
            }
        }

        /// <summary>
        /// Opens a form to edit the currently selected group.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void itmEdit_Click(object sender, EventArgs e) {
            if(lstAccounts.SelectedIndices.Count > 0) {
                ListViewItem selectedItem = lstAccounts.Items[lstAccounts.SelectedIndices[0]];
                INestable item = selectedItem.Tag as INestable;
                if(item is IAccount) {
                    IAccount account = item as IAccount;
                    try {
                        //account.Template = DalConfigurationManager.Provider.GetTemplateByID(account.Template.ID);
                    } catch(Exception ex) {
                        MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "ErrorLoadingTemplate"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                    }
                    using(FrmEditAccount frmEditAccount = new FrmEditAccount(account)) {
                        if(frmEditAccount.ShowDialog() == DialogResult.OK) {
                            try {
                                DalConfigurationManager.Provider.EditAccount(frmEditAccount.Account);
                            } catch(Exception ex) {
                                MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "ErrorSaving"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                            }
                        }
                    }
                } else if(item is IGroup) {
                    using(FrmEditGroup frmEditGroup = new FrmEditGroup(item as IGroup)) {
                        if(frmEditGroup.ShowDialog() == DialogResult.OK) {
                            try {
                                DalConfigurationManager.Provider.EditGroup(frmEditGroup.Group);
                            } catch(Exception ex) {
                                MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "ErrorSaving"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                            }
                        }
                    }

                }
                RefreshView();
            }
        }

        /// <summary>
        /// Deletes the currently selected item after showing a confirmation dialog.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void itmDelete_Click(object sender, EventArgs e) {
            if(lstAccounts.SelectedIndices.Count > 0) {
                ListViewItem selectedItem = lstAccounts.Items[lstAccounts.SelectedIndices[0]];
                INestable item = selectedItem.Tag as INestable;
                if(item is IAccount) {
                    if(MessageBox.Show(I18nUtils.GetString("Strings", "ConfirmDeleteAccountFmt", item.Name), I18nUtils.GetString("Strings", "ConfirmDeletion"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes) {
                        DalConfigurationManager.Provider.DeleteAccount(item.ID);
                    }
                } else if(item is IGroup) {
                    if(MessageBox.Show(I18nUtils.GetString("Strings", "DeleteGroupDesc"), I18nUtils.GetString("Strings", "ConfirmDeletion"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes) {
                        DalConfigurationManager.Provider.DeleteGroup(item as IGroup);
                    }
                }
                RefreshView();
            }
        }

        /// <summary>
        /// Displays the account or group which is currently selected in the account list.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void lstAccounts_ItemActivate(object sender, EventArgs e) {
            if(lstAccounts.SelectedIndices.Count > 0) {
                ListViewItem selectedItem = lstAccounts.Items[lstAccounts.SelectedIndices[0]];
                INestable item = selectedItem.Tag as INestable;
                if(item is IAccount) {
                    ShowAccount(item as IAccount);
                } else if(item is IGroup) {
                    ShowGroup((item as IGroup).ID, false);
                }
            }
        }

        /// <summary>
        /// Updates the account list to show only accounts from the specified Group.
        /// This is equivalent to the ReloadDatabase method in WPF - it checks the validity of the password.
        /// </summary>
        /// <param name="groupId">The ID of the group to show.</param>
        /// <param name="showParent"><c>true</c> if the group's parent should be shown.</param>
        private void ShowGroup(string groupId, bool showParent) {
            try {
                if(!File.Exists(DalConfigurationManager.Provider.FileName)) {
                    FrmSetupWizard frmSetupWizard = new FrmSetupWizard();
                    if(frmSetupWizard.ShowDialog() != DialogResult.OK) {
                        Application.Exit();
                    }
                }
                bool validPass = DalConfigurationManager.Provider.CheckPassword();
                if(!validPass) {
                    FrmPromptPass dlg = new FrmPromptPass();
                    if(dlg.ShowDialog() != DialogResult.OK) {
                        return;
                    }
                }
            } catch (Exception ex) {
                MessageBox.Show(ex.Message, I18nUtils.GetString("Errors", "Error"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                return;
            }
            if(showParent && !string.IsNullOrEmpty(groupId)) { // can't show parent if group is at root level
                var currentGroup = DalConfigurationManager.Provider.GetGroupByID(groupId);
                currentGroupId = currentGroup.ParentID;
            } else {
                currentGroupId = groupId;
            }
            KeyValuePair<IEnumerable<IGroup>, IEnumerable<IAccount>> children = DalConfigurationManager.Provider.GetItemsByParent(currentGroupId);

            itmBack.Text = string.IsNullOrEmpty(currentGroupId) ? I18nUtils.GetString("Strings", "Exit") : I18nUtils.GetString("Strings", "Back");
            lstAccounts.Items.Clear();
            foreach(IGroup childGroup in children.Key) {
                ListViewItem itm = new ListViewItem(new string[]
                                                        {
                                                            childGroup.Name
                                                        });
                itm.ImageIndex = 0;

                itm.Tag = childGroup;
                lstAccounts.Items.Add(itm);
            }
            foreach(IAccount account in children.Value) {
                ListViewItem itm = new ListViewItem(new string[]
                                                        {
                                                            account.Name
                                                        });
                itm.ImageIndex = WinMobileUtils.GetImagePosition(account.Icon);

                itm.Tag = account;
                lstAccounts.Items.Add(itm);
            }
            if(lstAccounts.Items.Count == 0) {
                lstAccounts.Items.Add(new ListViewItem(I18nUtils.GetString("Strings", "EmptyGroup")));
                lstAccounts.Enabled = false;
            } else {
                lstAccounts.Enabled = true;
            }
            lstAccounts.Focus();
        }
        
        /// <summary>
        /// Displays the specified account.
        /// </summary>
        /// <param name="account">The account to show.</param>
        private void ShowAccount(IAccount account) {
            //using(FrmShowAccount frmShowAccount = new FrmShowAccount(settings.Accounts[name] as Account, settings)) {
            using(FrmShowAccount frmShowAccount = new FrmShowAccount(account)) {
                if(frmShowAccount.ShowDialog() == DialogResult.OK) {
                    RefreshView();
                }
            }
        }

        /// <summary>
        /// Refreshes the current group.
        /// </summary>
        private void RefreshView() {
            ShowGroup(currentGroupId, false);
        }
        
        /// <summary>
        /// Displays a form to change program options.
        /// </summary>
        private void ShowOptions() {
            using(FrmOptions frmOptions = new FrmOptions()) {
                if(frmOptions.ShowDialog() == DialogResult.OK) {
                    ShowGroup(null, false);
                }
            }
        }
        
        /// <summary>
        /// Displays the 'About' dialog.
        /// </summary>
        private void ShowAbout() {
            using(FrmAbout frmAbout = new FrmAbout()) {
                frmAbout.ShowDialog();
            }
        }
    }
}